package demo2;
//使用volatile来解决

import java.util.Scanner;

/**
 * volatile 挥发性的单词翻译
 * 第一点：volatile只能用于成员变量，不能用于局部变量
 * volatile特性：
 * 1.直接可见性
 * 读屏障：对于flag的读取，会让缓存失效，每次都是从主内存中读取，每次都能读到最新的主内存中flag的值
 * 写屏障：对于flag的修改，修改后会立即将他写回主内存，所有线程中对于该变量的本地缓存会立即失效
 * 2.有序性：通过插入内存屏障（storestore，storeload，loadload，loadstore）四种屏障来保证有序性
 * 对于   storestore->volatile写 ->storeload
 * 对于   storeload ->volatile读 ->loadload/loadstore
 * 由于内存屏障的缘故，
 * 写传播:volatile 写会将之前的所有普通写操作结果刷新到主内存。
 * 读刷新:volatile 读会从主内存中读取最新值，并确保后续普通读操作能看到最新状态。
 * 这种对于普通变量的间接性可见性存在，但我们并不要去使用依赖，要想确保某个变量的可见性，并且禁止指令重排序的话，直接对那个变量使用volatile
 * 指令重排序的影响（1.变量半初始化 2.变量可见性问题 3.初始化顺序错乱）
 *
 */
//volatile写操作会在指令序列中插入内存屏障，这些屏障可能会影响相邻变量（如 flag）的缓存行为，尽管这并非 volatile 的标准语义。，
// 但是并不要依赖于这种间接性的可见性
public class DEMO_05 {
    static int flag = 0;
    volatile int a=1;
    public static void main(String[] args) {
//        volatile int a=1;     volatile只能用于成员变量，不能用于局部变量
        DEMO_05 demo_05=new DEMO_05();
        Thread t1 = new Thread(() -> {
            //实例化一个DEMO_04为了去调用a

            System.out.println("t1线程启动");
            while (flag == 0) {
                demo_05.a=2;
            }
            System.out.println("t1线程结束");
        });

        Thread t2 = new Thread(() -> {
            System.out.println("t2线程启动");
            Scanner scanner = new Scanner(System.in);
            System.out.println("请输入一个非零整数");
            flag = scanner.nextInt();
            System.out.println("t2线程结束");
        });
        //启动线程
        t1.start();
        t2.start();

    }
}
